package com.dataaccess.dataaccess.support.utils;

import cn.hutool.core.util.HexUtil;

import java.math.BigInteger;
import java.nio.ByteBuffer;

public class ByteUtil {

    private static String hexStr =  "0123456789ABCDEF";
    private static String[] binaryArray =
            {"0000","0001","0010","0011",
                    "0100","0101","0110","0111",
                    "1000","1001","1010","1011",
                    "1100","1101","1110","1111"};

    public static void main(String[] args)
    {
        String str = "二进制与十六进制互转测试";
        System.out.println("源字符串：\n"+str);

        String hexString = BinaryToHexString(str.getBytes());
        System.out.println("转换为十六进制：\n"+hexString);
        System.out.println("转换为二进制：\n"+bytes2BinaryStr(str.getBytes()));

        byte [] bArray = HexStringToBinary(hexString);
        System.out.println("将str的十六进制文件转换为二进制再转为String：\n"+new String(bArray));

    }
    /**
     *
     * @param str
     * @return 转换为二进制字符串
     */
    public static String bytes2BinaryStr(byte[] bArray){

        String outStr = "";
        int pos = 0;
        for(byte b:bArray){
            //高四位
            pos = (b&0xF0)>>4;
            outStr+=binaryArray[pos];
            //低四位
            pos=b&0x0F;
            outStr+=binaryArray[pos];
        }
        return outStr;

    }
    //返回16进制数组
    public static byte[] getBY(String str){
        String hexString = BinaryToHexString(str.getBytes());
        byte [] bArray = HexStringToBinary(hexString);
        return bArray;
    }
    //16进制字符串转2进制数组
    public static byte[] hexStr2Byte(String hex) {
        ByteBuffer bf = ByteBuffer.allocate(hex.length() / 2);
        for (int i = 0; i < hex.length(); i++) {
            String hexStr = hex.charAt(i) + "";
            i++;
            hexStr += hex.charAt(i);
            byte b = (byte) Integer.parseInt(hexStr, 16);
            bf.put(b);
        }
        return bf.array();
    }
    /**
     *
     * @param bytes
     * @return 将二进制转换为十六进制字符输出
     */
    public static String BinaryToHexString(byte[] bytes){

        String result = "";
        String hex = "";
        for(int i=0;i<bytes.length;i++){
            //字节高4位
            hex = String.valueOf(hexStr.charAt((bytes[i]&0xF0)>>4));
            //字节低4位
            hex += String.valueOf(hexStr.charAt(bytes[i]&0x0F));
            result +=hex+" ";
        }
        return result;
    }
    /**
     *
     * @param bytes
     * @return 将二进制转换为十六进制字符输出
     */
    public static String BinaryToHexString(byte[] bytes,int start,int end){

        String result = "";
        String hex = "";
        for(int i=start;i<end;i++){
            //字节高4位
            hex = String.valueOf(hexStr.charAt((bytes[i]&0xF0)>>4));
            //字节低4位
            hex += String.valueOf(hexStr.charAt(bytes[i]&0x0F));
            result +=hex+" ";
        }
        return result;
    }
    /**
     *
     * @param hexString
     * @return 将十六进制转换为字节数组
     */
    public static byte[] HexStringToBinary(String hexString){
        //hexString的长度对2取整，作为bytes的长度
        int len = hexString.length()/2;
        byte[] bytes = new byte[len];
        byte high = 0;//字节高四位
        byte low = 0;//字节低四位

        for(int i=0;i<len;i++){
            //右移四位得到高位
            high = (byte)((hexStr.indexOf(hexString.charAt(2*i)))<<4);
            low = (byte)hexStr.indexOf(hexString.charAt(2*i+1));
            bytes[i] = (byte) (high|low);//高地位做或运算
        }
        return bytes;
    }

    /**
     * 计算CRC16校验码
     *
     * @param bytes
     * @return
     */
    public static String getCRC(byte[] bytes) {
        int CRC = 0x0000ffff;
        int POLYNOMIAL = 0x0000a001;

        int i, j;
        for (i = 0; i < bytes.length; i++) {
            CRC ^= ((int) bytes[i] & 0x000000ff);
            for (j = 0; j < 8; j++) {
                if ((CRC & 0x00000001) != 0) {
                    CRC >>= 1;
                    CRC ^= POLYNOMIAL;
                } else {
                    CRC >>= 1;
                }
            }
        }
        String crc = Integer.toHexString(CRC);
        if (crc.length()==1){
            crc = "000"+crc;
        }else if (crc.length()==2){
            crc = "00"+crc;
        }else if (crc.length()==3){
            crc = "0"+crc;
        }
        return crc;
    }

    /**
     * hex字符串转换为byte[]
     *
     * @param hex
     * @return
     */
    public static byte[] hex2byte(String hex) {
        byte[] bts = new byte[hex.length() / 2];
        for (int i = 0, j = 0; j < bts.length; j++) {
            bts[j] = (byte) Integer.parseInt(hex.substring(i, i + 2), 16);
            i += 2;
        }
        return bts;
    }
    /**
     * @Author YangYu
     * @Description 十六进制转（整型）
     * @Date Created in 9:34 2021/5/19
     * @Param [strHex]
     */

    public static int hex16To10(String strHex) {
        BigInteger lngNum = new BigInteger(strHex, 16);
        return lngNum.intValue();
    }
    /**
     * @Author YangYu
     * @Description 十六进制转二进制字符串
     * @Date Created in 14:07 2021/11/24
     * @Param [hex]
     */

    public static String hexToBinaryString(String hex) {
        String str = Integer.toBinaryString(Integer.parseInt(hex,16));
        if(str.length() == 1){
            str = "0000000" + str;
        }else if(str.length() == 2){
            str = "000000" + str;
        }else if(str.length() == 3){
            str = "00000" + str;
        }else if(str.length() == 4){
            str = "0000" + str;
        }else if(str.length() == 5){
            str = "000" + str;
        }else if(str.length() == 6){
            str = "00" + str;
        }else if(str.length() == 7){
            str = "0" + str;
        }
        return str;
    }

    /**
     * @Author YangYu
     * @Description 十六进制转字符（ASCll码）
     * @Date Created in 16:18 2023/11/13
     * @Param [hex]
     */

    public static String hexToStr(String hex) {
        String number = new String(HexUtil.decodeHex(hex));
        return number;
    }
}
